package test.service;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;

import test.testcase.Params;
import test.testcase.TestCase;
import test.testcase.TestCaseApi;
import test.testcase.TestCaseData;
import test.testcase.TestStepAssert;
import test.testcase.TestStepParam;
import test.testcase.TestcaseStep;
import test.testcase.dao.AssertDao;
import test.testcase.dao.ParamDao;
import test.testcase.dao.TestCaseApiDao;
import test.testcase.dao.TestCaseDao;
import test.testcase.dao.TestModelDao;
import test.user.user;
import test.utils.GetValue;
import test.utils.JsonResult;
import test.utils.Mysql;

public class ServiceTestCase {
	
	private static Object[][] getCase(JsonResult result) {
		JSONArray array = result.read("data").toJsonArray();
		Map<String, TestCaseData> map = new HashMap<>();  
		int count = 0;  //默认有多少个用例
		for(int i=0;i<array.length();i++) {
			String caseid = array.getJSONObject(i).getString("id");
			TestCaseData testCaseData = getTestCaseDataByData(array.getJSONObject(i).getString("data"));
			map.put(caseid, testCaseData);
			if (testCaseData != null) {
				int count2 = testCaseData.getLineCount();
				if (count2 > 0) {
					count = count + count2 - 1; 
				}
			}
		}
		count = count + array.length(); // 计算最终的用例个数
		Object[][] objects = new Object[count][];
		int size = 0;
		for(int i=0;i<array.length();i++) {
			TestCase testCase = new TestCase();
			String caseid = array.getJSONObject(i).getString("id");
			testCase = getTestCase(caseid);
			TestCaseData testCaseData = map.get(caseid);
			 //数据文件数据行数
			if (testCaseData != null) {
				int lineNumber = map.get(caseid).getLineCount();
				if (lineNumber == 1) {
					Object[] object = new Object[2];
					object[0] = testCase;
					object[1] = testCaseData.getTestData().get(0);
					objects[size] = object;
				}else if (lineNumber > 1) {
					for(int j=0;j<lineNumber;j++) {
						if (j != 0) {
							size++;
						}
						Object[] object2 = new Object[2];
						object2[0] = testCase;
						object2[1] = testCaseData.getTestData().get(j);
						objects[size] = object2;
					}
				}
			}else {
				Object[] object3 = new Object[2];
				object3[0] = testCase;
				object3[1] = new HashMap<>();
				objects[size] = object3;
			}
			size++;
		}
		return objects;
	}
	
	public static Object[][] dataProvider(String projectid) {
		JsonResult result = TestCaseDao.getExcutableCases(projectid);
		JSONArray array = result.read("data").toJsonArray();
		if (array != null && array.length() > 0) {
			return getCase(result);
		}else {
			//如果没有用例，则执行项目用例
			result = TestCaseDao.getCases(projectid);
			array = result.read("data").toJsonArray();
			if (array != null && array.length() > 0) {
				return getCase(result);
			}
		}
		return null;
	}
	
	public static TestCaseData getTestDataByCaseId(String caseId) {
		TestCaseData testCaseData = new TestCaseData();
		testCaseData.setCaseId(caseId);
		JsonResult result = TestCaseDao.getTestDataByCaseId(caseId);
		JSONArray array = result.read("data").toJsonArray();
		if (array != null && array.length() == 1) {
			String data = array.getJSONObject(0).getString("data");
			return getTestCaseDataByData(data);
		}
		return null;
	}
	
	private static TestCaseData getTestCaseDataByData(String data) {
		if (data != null && !"".equals(data)) {
			TestCaseData testCaseData = new TestCaseData();
			BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));  
			 String line;
			 int count 	= 0;
			 List<Map<String, String>> testdata1 = new ArrayList<>();
			 try {
				while ( (line = br.readLine()) != null ) {  
				     if(!line.trim().equals("")){
				    	 //读到每一行
				    	 if (count == 0) { //如果是第一行
							String [] keys = line.split(",");
							testCaseData.setColumnCount(keys.length);
							List<String> kList = new ArrayList<>();
							for(int i=0;i<keys.length;i++) {
								kList.add("$"+keys[i]);
							}
							testCaseData.setKeys(kList);	
				    	 }else {
				    		 Map<String, String> map = new HashMap<>();
				    		 String [] values = line.split(",");
				    		 for(int j=0;j<testCaseData.getColumnCount();j++) {
				    			 map.put(testCaseData.getKeys().get(j), values[j]);
				    		 }
				    		 testdata1.add((Map<String, String>) map);
				    	 }
				    	 count++;
				     }       		    	 
				}
			} catch (IOException e) {
				e.printStackTrace();
			} 
			testCaseData.setTestData(testdata1);
			testCaseData.setLineCount(testdata1.size());
			return testCaseData;
		}
		return null;
	}
	
	public static TestCase getTestCase(String caseid) {
		TestCase testCase = new TestCase();
		testCase.setCaseid(caseid);
		JsonResult result = TestCaseDao.getTestCaseInfo(caseid);
		return setTestCase(testCase, result.read("data[0]").toJsonObject());
	}
	
	private static TestCase setTestCase(TestCase testCase, JSONObject object) {
		testCase.setCasename(object.getString("casename"));
		testCase.setCaseinfo(object.getString("caseinfo"));
		testCase.setPriority(object.getString("priority"));
		testCase.setPriorityname(object.getString("priorityname"));
		testCase.setInserttime(object.getString("inserttime"));
		testCase.setUpdatetime(object.getString("updatetime"));
		testCase.setStatus(object.getString("status"));
		testCase.setUserid(object.getString("userid"));
		testCase.setUsername(object.getString("username"));
		testCase.setProjectid(object.getString("projectid"));
		testCase.setProjectname(object.getString("projectname"));
		testCase.setTypetag(object.getString("typetag"));
		testCase.setChannel(object.getString("channel"));
		testCase.setTypetagname(object.getString("typetagname"));
		testCase.setCount_e(object.getString("count_success"));
		testCase.setCount_e(object.getString("count_fail"));
		testCase.setCount_e(object.getString("count_error"));
		testCase.setCount_e(object.getString("last_excute_time"));
		
		return testCase;
	}
	
	public static int getOrderNum(String caseid) {
		JsonResult result = TestCaseDao.getLastTestStep(caseid);
		if (result.read("data[0]").toJsonObject() == null) {
			return 1;
		}else {
			return result.read("data[0].order").toInt()+1;
		}
	}
	
	public static TestStepAssert getTestStepAssert(TestcaseStep step) {
		TestStepAssert testStepAssert = new TestStepAssert();
		JsonResult result = TestCaseDao.getTestStepAssert(step);
		if (result.read("data").toJsonArray() != null) {
			JSONArray array = result.read("data").toJsonArray();
			for(int i=0;i<array.length();i++) {
				JSONObject object = array.getJSONObject(i);
				testStepAssert.addAssert(object.getString("expression"));
			}
		}
		return testStepAssert;
	}
	
	public static TestStepParam getTestStepParam(TestcaseStep testcaseStep) {
		TestStepParam testStepParam = new TestStepParam();
		JsonResult result = TestCaseDao.getTestStepParam(testcaseStep);
		JSONArray array = result.read("data").toJsonArray();
		if (array != null) {
			for(int i=0;i<array.length();i++) {
				JSONObject object = array.getJSONObject(i);
				Params p = new Params();
				p.setCaseid(testcaseStep.getCaseid());
				p.setExpression(object.getString("expression"));
				p.setId(object.getString("ID"));
				p.setMethod(object.getString("method"));
				p.setParamname(object.getString("paramname"));
				p.setStepid(testcaseStep.getId());
				testStepParam.addParam(p);
			}
		}
		return testStepParam;
	}
	
	public static TestcaseStep getTestCaseStep(String stepid) {
		JsonResult result = TestCaseDao.getTestcaseStep(stepid);
		TestcaseStep testcaseStep = new TestcaseStep();
		testcaseStep.setId(stepid);
		testcaseStep.setCaseid(result.read("data[0].caseid").toString());
		testcaseStep.setStepname(result.read("data[0].stepname").toString());
		testcaseStep.setFunctionname(result.read("data[0].functionname").toString());
		testcaseStep.setOperateid(result.read("data[0].operateid").toString());
		testcaseStep.setInserttime(result.read("data[0].inserttime").toString());
		testcaseStep.setUpdatetime(result.read("data[0].updatetime").toString());
		testcaseStep.setBody(result.read("data[0].body").toString());
		testcaseStep.setOrder(result.read("data[0].order").toString());
		testcaseStep.setParams(getTestStepParam(testcaseStep));
		testcaseStep.setAsserting(getTestStepAssert(testcaseStep));
		testcaseStep.setHeader(result.read("data[0].header").toString());
		return testcaseStep;
	}
	
	public static boolean isJobContainCase(String caseid) {
		JsonResult result = TestCaseDao.getJobCaseCount(caseid);
		if (result.read("data[0].count").toInt() > 0) {
			return true;
		}else {
			return false;
		}
	}
	
	public static String getLastCaseId() {
		JsonResult result = TestCaseDao.getLastCaseId();
		return result.read("data[0].id").toString();
	}
	
	public static JsonResult copyCase(String id) {
		TestCase testcase = getTestCase(id);
		String channel = "";
		if (testcase.getChannel().equals("PC")) {
			channel = "WECHAT";
		}else if (testcase.getChannel().equals("WECHAT")) {
			channel = "APP";
		}else if (testcase.getChannel().equals("APP")) {
			channel = testcase.getChannel();
		}
		TestCaseDao.copyTestCase(channel, id);
		String newcaseid = getLastCaseId();
		JsonResult result = TestCaseDao.getTestCaseData(id);
		String newTestData = result.read("data[0].data").toString();
		JSONArray array = TestCaseDao.getTestSteps(id).read("data").toJsonArray();
		if (array != null) {
			for(int i=0;i<array.length();i++) {
				String stepid = array.getJSONObject(i).getString("ID");
				TestcaseStep step = getTestCaseStep(stepid);
				List<Params> params = step.getParams().getParams();
				List<String> asserts = step.getAsserting().getAssertstr();
				TestCaseDao.addTestCaseStep(newcaseid, step.getStepname(), step.getFunctionname(), step.getOperateid(), step.getBody().replace("\\", "\\\\\\"), step.getOrder());
				String newstepid = getLastStepId();
				if (params != null) {
					for(int j=0;j<params.size();j++) {
						Params params2 = params.get(j);
						ParamDao.addTestCaseParam(newcaseid, newstepid, params2.getParamname(), params2.getMethod(), params2.getExpression().replace("\\", "\\\\"));
					}
				}
				if (asserts != null) {
					for(int j=0;j<asserts.size();j++) {
						String assertting = asserts.get(j);
						AssertDao.addTestCaseAssert(newcaseid, newstepid, assertting);
					}
				}
			}
		}
		
		if (newTestData != null) {
			Mysql.excute("insert into testcasedata values("+getLastCaseId()+",'"+newTestData+"')");
		}
		return new JsonResult();
	}
	
	public static String getLastStepId() {
		JsonResult result = TestCaseDao.getLastStepId();
		return result.read("data[0].ID").toString();
	}
	
	public static JsonResult copyCaseToModel(String id) {
		TestCase testCase = getTestCase(id);
		JsonResult result = TestCaseDao.getStepCountNoModel(id);
		if (result.read("data[0].count").toInt() == 0) {
			return null;
		}
		TestModelDao.copyModel(testCase.getTypetagname()+"|"+testCase.getCasename(), id);
		String newmodelid = TestModelDao.getLastModelId();
		JSONArray array = TestCaseDao.getTestSteps(id).read("data").toJsonArray();
		if (array != null) {
			for(int i=0;i<array.length();i++) {
				String stepid = array.getJSONObject(i).getString("ID");
				TestcaseStep step = getTestCaseStep(stepid);
				List<Params> params = step.getParams().getParams();
				List<String> asserts = step.getAsserting().getAssertstr();
				TestModelDao.addModelStep(newmodelid, step.getStepname(), step.getFunctionname(), step.getOperateid(), step.getBody().replace("\\", "\\\\"), "ALL", step.getOrder());
				String newstepid = ServiceTestModel.getLastModelStepId();
				if (params != null) {
					for(int j=0;j<params.size();j++) {
						Params params2 = params.get(j);
						ParamDao.addModelParam(newmodelid, newstepid, params2.getParamname(), params2.getMethod(), params2.getExpression().replace("\\", "\\\\"));
					}
				}
				if (asserts != null) {
					for(int j=0;j<asserts.size();j++) {
						String assertting = asserts.get(j);
						AssertDao.addModelAssert(newmodelid, newstepid, assertting);
					}
				}
			}
		}
		ParamDao.delParamByCaseId(id);
		AssertDao.delAssertByCaseId(id);
		TestCaseDao.delTestStep(id);
		String name = TestModelDao.getTestModelInfo(newmodelid).read("data[0].modelname").toString();
		return TestCaseDao.addmodelforcase(id, name, newmodelid, getOrderNum(id)+"");
	}
	
	public static boolean isTestData(String testdata) {
		if (testdata == null || "".equals(testdata)) {
			return true;
		}
		BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(testdata.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));  
		 String line;
		 int count = 0; //行数
		 int firstCount = 0;  //列数
		 try {
			while ( (line = br.readLine()) != null ) {  
			     if(!line.trim().equals("")){
			    	 //读到每一行
			    	 if (count == 0) { //如果是第一行
						String [] keys = line.split(",");
						firstCount = keys.length;
			    	 }else {
			    		 String [] values = line.split(",");
			    		 if (values.length != firstCount) {
							return false;
						}
			    	 }
			    	 count++;
			     }       		    	 
			}
		} catch (IOException e) {
			e.printStackTrace();
		} 
		if (count <= 1) {
			return false;
		}
		return true;
	}
	
	public static boolean isTestCaseExcuting(TestCase testCase, user user) {
		JsonResult result = TestCaseDao.getExcutingTestCase(testCase, user);
		if (result.read("data").toJsonArray() != null && result.read("data").toJsonArray().length()>0 ) {
			String starttime = result.read("data[0].starttime").toString();
			long start = date2TimeStamp(starttime, "yyyy-MM-dd HH:mm:ss");
			long now = date2TimeStamp(GetValue.nowDateTimeStr("yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss");
			if ((now-start)>30) {
				return false;
			}
			return true;
		}else {
			return false;
		}
	}
	
	public static long date2TimeStamp(String date_str,String format) {
		try {  
	        SimpleDateFormat sdf = new SimpleDateFormat(format);  
	        return sdf.parse(date_str).getTime()/1000;
	    } catch (Exception e) {  
	        e.printStackTrace();  
	    }  
	    return 0; 
    } 
	
	public static boolean saveTestCaseRequestStep(JSONObject object, String body, String stepid, String userid) {
		if (object != null) {
			TestcaseStep step = getTestCaseStep(stepid);
			//先去找请求
			JSONArray apiarr = TestCaseDao.getApi(object.getString("api"), object.getString("method")).read("data").toJsonArray();
			String apiid = "";
			if (apiarr != null && apiarr.length()>0) {
				apiid = apiarr.getJSONObject(0).getString("id");
				TestCaseApiDao.update(apiid, object.getString("contenttype"));
			}else {
				if (body == null || "null".equals(body)) {
					body = "";
				}
				TestCaseApi api = new TestCaseApi();
				api.setContenttypeid(object.getString("contenttype"));
				api.setUrl(object.getString("api"));
				api.setMethod(object.getString("method"));
				TestCase testCase = getTestCase(step.getCaseid());
				api.setProjectid(testCase.getProjectid());
				api.setUserid(userid);
				TestCaseDao.addApi(api);
				apiarr = TestCaseDao.getApi(object.getString("api"), object.getString("method")).read("data").toJsonArray();
				if (apiarr != null && apiarr.length()>0) {
					apiid = apiarr.getJSONObject(0).getString("id");
				}
			}
			TestCaseDao.updateTestStep(object.getString("stepname"), apiid, body, stepid);
			ParamDao.delTestStepParam(stepid);
			AssertDao.delTestStepAssert(stepid);
			for(int i=1;i<=5;i++) {
				if (!"".equals(object.getString("paramname"+i)) && !"".equals(object.getString("xuanqufangshi"+i))) {
					String rule = "";
					if (object.getString("xuanqufangshi"+i).equals("leftright") && !"".equals(object.getString("left"+i)) && !"".equals(object.getString("right"+i))) {
						rule = object.getString("left"+i)+"|"+object.getString("right"+i);
					}else if (object.getString("xuanqufangshi"+i).equals("jsonPath") && !"".equals(object.getString("paramname"+i))) {
						rule = object.getString("rule"+i);
					}
					if (!"".equals(rule)) {
						ParamDao.addTestCaseParam(step.getCaseid(), stepid, object.getString("paramname"+i), object.getString("xuanqufangshi"+i), rule);
					}
				}
			}
			String headers = "";
			for(int i=1;i<=5;i++) {
				if (!"".equals(object.getString("headervalue"+i)) && !"".equals(object.getString("headerkey"+i))) {
					headers += "&"+ object.getString("headerkey"+i)+"="+object.getString("headervalue"+i);
				}
			}
			TestCaseDao.updateTestStepHeader(headers, stepid);

			for(int i=1;i<=5;i++) {
				if (!"".equals(object.getString("sjjg"+i))) {
					String rule = object.getString("sjjg"+i)+object.getString("dygz"+i)+object.getString("yqjg"+i);
					AssertDao.addTestCaseAssert(step.getCaseid(), stepid, rule);
				}
			}
			return true;
		}
		return false;
	}

	public static boolean addTestCaseRequestStep(JSONObject object,String body, String testcaseid, String userid) {
		if (object != null) {
			//先去找请求
			JSONArray apiarr = TestCaseDao.getApi(object.getString("api"), object.getString("method")).read("data").toJsonArray();
			String apiid = "";
			if (apiarr != null && apiarr.length()>0) {
				apiid = apiarr.getJSONObject(0).getString("id");
			}else {
				if (body == null || "null".equals(body)) {
					body = "";
				}
				TestCaseApi api = new TestCaseApi();
				api.setContenttypeid(object.getString("contenttype"));
				api.setUrl(object.getString("api"));
				api.setMethod(object.getString("method"));
				TestCase testCase = getTestCase(testcaseid);
				api.setProjectid(testCase.getProjectid());
				api.setUserid(userid);
				TestCaseDao.addApi(api);
				apiarr = TestCaseDao.getApi(object.getString("api"), object.getString("method")).read("data").toJsonArray();
				if (apiarr != null && apiarr.length()>0) {
					apiid = apiarr.getJSONObject(0).getString("id");
				}
			}
			TestCaseDao.addTestCaseStep(testcaseid, object.getString("stepname"), "request", apiid, body, getOrderNum(testcaseid)+"");
			String stepid = getLastStepId();
			for(int i=1;i<=5;i++) {
				if (!"".equals(object.getString("paramname"+i)) && !"".equals(object.getString("xuanqufangshi"+i))) {
					String rule = "";
					if (object.getString("xuanqufangshi"+i).equals("leftright") && !"".equals(object.getString("left"+i)) && !"".equals(object.getString("right"+i))) {
						rule = object.getString("left"+i)+"|"+object.getString("right"+i);
					}else if (object.getString("xuanqufangshi"+i).equals("jsonPath") && !"".equals(object.getString("paramname"+i))) {
						rule = object.getString("rule"+i);
					}
					if (!"".equals(rule)) {
						ParamDao.addTestCaseParam(testcaseid, stepid, object.getString("paramname"+i), object.getString("xuanqufangshi"+i), rule);
					}
				}
			}
			String headers = "";
			for(int i=1;i<=5;i++) {
				if (!"".equals(object.getString("headervalue"+i)) && !"".equals(object.getString("headerkey"+i))) {
					headers += "&"+ object.getString("headerkey"+i)+"="+object.getString("headervalue"+i);
				}
			}
			TestCaseDao.updateTestStepHeader(headers, stepid);
			for(int i=1;i<=5;i++) {
				if (!"".equals(object.getString("sjjg"+i))) {
					String rule = object.getString("sjjg"+i)+object.getString("dygz"+i)+object.getString("yqjg"+i);
					AssertDao.addTestCaseAssert(testcaseid, stepid, rule);
				}
			}
			return true;
		}
		return false;
	}
	
}
